﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using SHomeWorkshop.LunarConcept.Tools;
using System.Windows.Controls;
using SHomeWorkshop.LunarConcept.ModifingManager;
using System.Xml;
using System.Windows.Input;
using System.Windows.Media;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Enums;
using System.Windows.Media.Imaging;
using SHomeWorkshop.LunarConcept.Converters;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月2日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：为可以内嵌内容（Content）的部件提供的基类。这类部件需要自定义左上角的坐标。
    ///           目前，Content部件包括：TextArea/PictureBox/Group。二○一二年六月八日
    /// </summary>
    public abstract class ContentWidget : Widget, ICanBeLinkedWidget, ITextRotate, IWidgetPadding
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [构造方法]此类只是中间类，不作为任何具体的类。不应直接调用此构造方法。
        /// </summary>
        /// <param name="masterPageEditor">所属的PageEditor。</param>
        public ContentWidget(Controls.PageEditor masterPageEditor)
            : base(masterPageEditor)
        {
            this.layerIndex = WidgetLayerIndex.ContentWidget;
            RefreshLayerIndex();

            this.Child = this.mainBorder;

            this.selectedAdorner = new WidgetSelectedAdorner(this.mainBorder, this);
            this.AdornerLayer.Add(this.selectedAdorner);

            this.mainBorder.PreviewMouseLeftButtonDown +=
                new System.Windows.Input.MouseButtonEventHandler(mainBorder_PreviewMouseLeftButtonDown);
            this.mainBorder.PreviewMouseLeftButtonUp +=
                new System.Windows.Input.MouseButtonEventHandler(mainBorder_PreviewMouseLeftButtonUp);
            this.mainBorder.PreviewMouseRightButtonUp +=
                new System.Windows.Input.MouseButtonEventHandler(mainBorder_PreviewMouseRightButtonUp);

            this.maskAdorner = new MaskAdorner(this);
            this.maskAdorner.PreviewMouseLeftButtonDown +=
                new MouseButtonEventHandler(maskAdorner_PreviewMouseLeftButtonDown);
            this.AdornerLayer.Add(this.maskAdorner);//注意它要在linkerAdorner底层。

            this.linkerAdorner = new WidgetLinkerAdorner(this.mainBorder, this);
            this.AdornerLayer.Add(this.linkerAdorner);
            this.linkerAdorner.MouseRightButtonDown += new MouseButtonEventHandler(linkerAdorner_MouseRightButtonDown);
            this.linkerAdorner.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(linkerAdorner_PreviewMouseLeftButtonDown);
            this.linkerAdorner.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(linkerAdorner_PreviewMouseLeftButtonUp);

            //外框装饰器
            this.outerBorderAdorner = new OuterBorderAdorner(this.mainBorder, this);
            this.AdornerLayer.Add(this.outerBorderAdorner);
            this.outerBorderAdorner.MouseLeftButtonDown += mainBorder_PreviewMouseLeftButtonDown;

            //中点装饰器。
            this.centerAdorner = new WidgetCenterAdorner(this.mainBorder, this, Brushes.Black) { ToolTip = "按鼠标左键向外拖动，生成关系节点" };
            this.centerAdorner.PreviewMouseRightButtonUp += new MouseButtonEventHandler(centerAdorner_PreviewMouseRightButtonUp);
            this.AdornerLayer.Add(this.centerAdorner);
            this.centerAdorner.MouseLeftButtonDown +=
                new MouseButtonEventHandler(centerAdorner_MouseLeftButtonDown);


            this.commentAdorner = new CommentAdorner(this.mainBorder, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。
            this.commentAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(commentAdorner_MouseLeftButtonUp);
            this.AdornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainBorder, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);
            this.AdornerLayer.Add(this.hyperLinkAdorner);
        }

        #endregion

        #region 字段与属性===================================================================================================

        /// <summary>
        /// [只读]返回右下角坐标。
        /// </summary>
        public override Point BottomRight
        {
            get
            {
                Size size = this.mainBorder.RenderSize;
                if (size.Width == 0 || size.Height == 0)
                {
                    this.InvalidateArrange();//没这个就不成。
                    this.UpdateLayout();
                    size = this.mainBorder.RenderSize;
                }

                return new Point(location.X + size.Width, location.Y + size.Height);
            }
        }

        /// <summary>
        /// 下备注文本装饰器。
        /// </summary>
        private WidgetCommentAdorner commentBottomAdorner = null;

        /// <summary>
        /// 上备注文本装饰器。
        /// </summary>
        private WidgetCommentAdorner commentTopAdorner = null;

        private string commentBottomText = string.Empty;
        /// <summary>
        /// [读写]部件下注释文本。
        /// </summary>
        [Tools.LunarProperty("CommentBottomText", PropertyDateType.String)]
        public string CommentBottomText
        {
            get { return commentBottomText; }
            set
            {
                commentBottomText = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CommentBottomTextTag, value);
                }

                this.RefreshCustomCommentText();
            }
        }

        private string commentTopText = string.Empty;
        /// <summary>
        /// [读写]部件上注释文本。
        /// </summary>
        [Tools.LunarProperty("CommentTopText", PropertyDateType.String)]
        public string CommentTopText
        {
            get { return commentTopText; }
            set
            {
                commentTopText = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.CommentTopTextTag, value);
                }

                this.RefreshCustomCommentText();
            }
        }

        /// <summary>
        /// [只读]表示当前部件是否被某个连接线挂接着。
        /// </summary>
        public bool IsLinked
        {
            get
            {
                if (this.masterEditor == null) return false;

                foreach (UIElement ue in this.masterEditor.Children)
                {
                    ILinkableLine linkedLine = ue as ILinkableLine;
                    if (linkedLine == null) continue;

                    if (linkedLine.StartMasterId == this.id || linkedLine.EndMasterId == this.id) return true;
                }

                return false;
            }
        }

        private string linkedPageEditorId = string.Empty;
        /// <summary>
        /// [读写]链接到的页面。——准备提供跳转到指定页面功能。
        /// ★默认值为string.Empty。
        /// ★null会被视为string.Empty。
        /// </summary>
        [Tools.LunarProperty("LinkedPageEditorId", PropertyDateType.String)]
        public string LinkedPageEditorId
        {
            get { return linkedPageEditorId; }
            set
            {
                string newLinkedPageEditorId = (value == null) ? string.Empty : value;
                linkedPageEditorId = newLinkedPageEditorId;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.LinkedPageEditorIdTag, newLinkedPageEditorId);
                }

                this.RefreshLinkedPageEditorId();
            }
        }

        public void RefreshLinkedPageEditorId()
        {
            if (string.IsNullOrEmpty(this.linkedPageEditorId))
            {
                this.linkerAdorner.ToolTip = "左键点击跳转到目标页，\r\n右键点击设置目标页";
                return;
            }

            if (this.masterEditor == null || this.masterEditor.MasterManager == null)
            {
                this.linkerAdorner.ToolTip = "左键点击跳转到目标页，\r\n右键点击设置目标页";
                return;
            }

            PageEditor destPage = this.masterEditor.MasterManager.GetPageEditor(this.linkedPageEditorId);
            if (destPage == null)
            {
                this.linkerAdorner.ToolTip = "未找到链接的页面，此页可能已经被删除";
                return;
            }

            this.linkerAdorner.InvalidateVisual();

            int pageIndex = this.masterEditor.MasterManager.Children.IndexOf(destPage);

            this.linkerAdorner.ToolTip = string.Format("链接至第{0,4} 页：{1}", pageIndex + 1,
                string.IsNullOrEmpty(destPage.PageTitle) ? "" : destPage.PageTitle);
        }

        protected Point location = new Point();
        /// <summary>
        /// 部件左上角位置。
        /// </summary>
        [LunarConcept.Tools.LunarProperty("Location", Enums.PropertyDateType.Point)]
        public Point Location
        {
            get { return location; }
            set
            {
                location = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.LocationTag, location.ToString());
                }

                this.RefreshLocation();
            }
        }

        protected WidgetCenterAdorner centerAdorner;
        /// <summary>
        /// [只读]用于“拖出自动连接线”的装饰器。一般应在中心位置。
        /// </summary>
        public WidgetCenterAdorner CenterAdorner
        {
            get { return centerAdorner; }
        }

        protected OuterBorderAdorner outerBorderAdorner;
        /// <summary>
        /// [只读]外框装饰器。
        /// </summary>
        public OuterBorderAdorner OuterBorderAdorner
        {
            get { return outerBorderAdorner; }
        }

        private OuterBorderType outerBorderType = OuterBorderType.Rect;
        /// <summary>
        /// [读写]外框类型。默认应矩形，不使用装饰器呈现；除矩形外其它外框以装饰器呈现。
        /// </summary>
        [Tools.LunarProperty("OuterBorderType", PropertyDateType.OuterBorderType)]
        public OuterBorderType OuterBorderType
        {
            get { return outerBorderType; }
            set
            {
                outerBorderType = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.OuterBorderTypeTag, outerBorderType.ToString());
                }

                RefreshOuterBorderType();
            }
        }

        private Adorners.WidgetLinkerAdorner linkerAdorner;
        /// <summary>
        /// [只读]链接装饰器。用于链接到某一个页面，以便跳转。
        /// </summary>
        protected Adorners.WidgetLinkerAdorner LinkerAdorner
        {
            get { return linkerAdorner; }
        }

        protected Border mainBorder = new Border() { Padding = new Thickness(10), Cursor = Cursors.Hand };
        /// <summary>
        /// [只读]主Border。用以承载其它部件内嵌内容。
        /// </summary>
        public Border MainBorder
        {
            get { return mainBorder; }
        }

        private MaskType mask = MaskType.None;
        /// <summary>
        /// [读写]遮罩类型。
        /// </summary>
        [Tools.LunarProperty("Mask", PropertyDateType.MaskType)]
        public MaskType Mask
        {
            get { return mask; }
            set
            {
                mask = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.MaskTag, value.ToString());
                }

                this.maskAdorner.InvalidateVisual();
            }
        }

        /// <summary>
        /// 遮罩装饰器。
        /// </summary>
        private MaskAdorner maskAdorner;

        public override System.Windows.Rect OuterRect
        {
            get
            {
                Rect r = new Rect(TopLeft, BottomRight);
                return r;
            }
        }

        /// <summary>
        /// 部件正在被拖动时的外边框。
        /// </summary>
        public Rect MovingRect
        {
            get
            {
                Rect rect = new Rect(Canvas.GetLeft(this), Canvas.GetTop(this),
                    this.ActualWidth, this.ActualHeight);

                return rect;
            }
        }

        /// <summary>
        /// 标示此部件是否处于“被选定”状态的装饰器。
        /// </summary>
        protected WidgetSelectedAdorner selectedAdorner;

        protected double textRotateAngle = 0;
        /// <summary>
        /// [读写]文本旋转角度。取值范围：[-180,180]。
        /// </summary>
        [Tools.LunarProperty("TextRotateAngle", PropertyDateType.Double)]
        public double TextRotateAngle
        {
            get { return textRotateAngle; }
            set
            {
                if (value > 180)
                {
                    textRotateAngle = 180;
                }
                else if (value < -180)
                {
                    textRotateAngle = -180;
                }
                else
                {
                    textRotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextRotateAngleTag, textRotateAngle.ToString());
                }

                this.RefreshTextRotateAngle();
            }
        }

        public override Point TopLeft
        {
            get { return location; }
        }

        /// <summary>
        /// [读写]此属性是Location属性的别名。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return location; }
            set { Location = value; }
        }

        /// <summary>
        /// [事实只读]ContentWidget是自适应大小的，因而此属性虽然可以赋值，但赋值后什么都不会发生。
        /// 　　　　　——此属性可写，只是因为ICanBeLinkedWidget接口的需要。InsertRelation命令依赖此属性。2012年6月1日
        /// 　　　　　此属性返回的值与BottomRight的返回值相同。
        /// </summary>
        public Point EndPoint
        {
            get { return BottomRight; }
            set { return; }
        }

        //2012年6月26日此属性被取消，改用WidgetLineWidth属性。
        //protected double widgetBorderWidth = 0;
        ///// <summary>
        ///// [读写]部件边框宽度。默认为2。
        ///// </summary>
        //[Tools.LunarProperty("WidgetBorderWidth", PropertyDateType.Double)]
        //public double WidgetBorderWidth
        //{
        //    get { return widgetBorderWidth; }
        //    set
        //    {
        //        widgetBorderWidth = value;
        //        if (this.xmlData != null)
        //        {
        //            this.xmlData.SetAttribute(XmlTags.WidgetBorderWidth, value.ToString());
        //        }
        //        this.RefreshWidgetBorderWidth();
        //    }
        //}

        protected Thickness widgetPadding = new Thickness(0);
        /// <summary>
        /// [读写]部件内部空隙宽。默认值为0。
        /// </summary>
        [Tools.LunarProperty("WidgetPadding", PropertyDateType.Thickness)]
        public Thickness WidgetPadding
        {
            get { return widgetPadding; }
            set
            {
                widgetPadding = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.WidgetPaddingTag, Globals.ThickConverter.ConvertToString(value));
                }
                this.RefreshWidgetPadding();
            }
        }
        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// 生成部件的内容。此方法应由派生类在重写时调用。
        /// </summary>
        public override void Build()
        {
            base.Build();

            try
            {
                XmlAttribute attrMask = this.xmlData.GetAttribute(XmlTags.MaskTag);
                if (attrMask != null)
                {
                    this.mask = (MaskType)Enum.Parse(typeof(MaskType), attrMask.Value);
                }

                XmlAttribute attrCommentBottomText = this.xmlData.GetAttribute(XmlTags.CommentBottomTextTag);
                if (attrCommentBottomText != null)
                {
                    this.commentBottomText = attrCommentBottomText.Value;
                }

                XmlAttribute attrCommentTopText = this.xmlData.GetAttribute(XmlTags.CommentTopTextTag);
                if (attrCommentTopText != null)
                {
                    this.commentTopText = attrCommentTopText.Value;
                }

                XmlAttribute attrLinkedPageEditorId = this.xmlData.GetAttribute(XmlTags.LinkedPageEditorIdTag);
                if (attrLinkedPageEditorId != null)
                {
                    this.linkedPageEditorId = attrLinkedPageEditorId.Value;
                }

                XmlAttribute attrLocation = this.xmlData.GetAttribute(XmlTags.LocationTag);
                if (attrLocation != null)
                {
                    this.location = Point.Parse(attrLocation.Value);
                }

                XmlAttribute attrTextRotateAngle = this.xmlData.GetAttribute(XmlTags.TextRotateAngleTag);
                if (attrTextRotateAngle != null)
                {
                    this.textRotateAngle = double.Parse(attrTextRotateAngle.Value);
                }

                XmlAttribute attrOuterBorderType = this.xmlData.GetAttribute(XmlTags.OuterBorderTypeTag);
                if (attrOuterBorderType != null)
                {
                    this.outerBorderType = (Enums.OuterBorderType)Enum.Parse(typeof(Enums.OuterBorderType), attrOuterBorderType.Value);
                }

                this.RefreshLocation();
                this.RefreshMask();
                this.RefreshCustomCommentText();

                //到ContentWidget为止，这个类分支已经实现了所需要的与WidgetStyle相关的所有属性。
                //上层的Widget已经实现了WidgetForeColor、IsShadowVisiable和WidgetOpacity并调用了相应的Refreshxxx()方法。
                //ContentWidget不需要WidgetStyle中的LineDash和Arrows属性。
                //因此调用，
                this.RefreshWidgetLineColor();
                this.RefreshWidgetLineWidth();
                this.RefreshWidgetBackColor();
                this.RefreshWidgetPadding();

                this.RefreshTextRotateAngle();
                this.RefreshOuterBorderType();

            }
            catch (Exception ex)
            {
                MessageBox.Show("　　构造内容部件时出现错误。异常信息如下：\r\n" + ex.Message + "\r\n" + ex.StackTrace,
                    Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        protected override void BuildStyleProperties()
        {
            base.BuildStyleProperties();

            if (this.xmlData == null) return;

            WidgetStyle defStyleOfDoc;
            if (this.masterEditor != null && this.masterEditor.MasterManager != null)
            {
                defStyleOfDoc = this.masterEditor.MasterManager.GetDefaultWidgetStyle(this.WidgetClassName);
            }
            else
            {
                defStyleOfDoc = WidgetStyle.FromWidgetClassName(this.WidgetClassName);
            }

            //到ContentWidget为止，WidgetStyle中相关属性只有padding还未读取。
            XmlAttribute attrWidgetPadding = this.xmlData.GetAttribute(XmlTags.WidgetPaddingTag);
            if (attrWidgetPadding != null)
            {
                this.widgetPadding = (Thickness)Globals.ThickConverter.ConvertFromString(attrWidgetPadding.Value);
            }
            else
            {
                this.widgetPadding = defStyleOfDoc.WidgetPadding;
            }
        }

        public override void BuildWidgetStylePropertiesAndRefresh()
        {
            base.BuildWidgetStylePropertiesAndRefresh();
            //已调用虚方法this.BuildStyleProperties();

            this.RefreshWidgetBackColor();
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshWidgetPadding();

            //ContentWidget不需要这两个StyleProperties.
            //this.RefreshArrows();
            //this.RefreshLineDash();

            //下面这几个的“最终实现类”就是Widget类。因此，已在基类（Widget类）中调用。
            //this.RefreshWidgetForeColor();
            //this.RefreshWidgetOpacity();
            //this.RefreshIsShadowVisible();
        }

        /// <summary>
        /// 关联事件。右击中心装饰器时，活动此部件。
        /// </summary>
        void centerAdorner_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.mainBorder_PreviewMouseRightButtonUp(sender, e);
        }

        /// <summary>
        /// 使用EditorManager.FormatBrush来格式化此部件。
        /// 
        /// </summary>
        /// <returns>如果被格式化，说明不是要进行选定状态的改变。</returns>
        public bool FormatSelf(ref ModifingItem<Action, ModifingInfo> mi, ref ModifingInfo info)
        {
            if (this.masterEditor == null || this.masterEditor.MasterManager == null) return false;

            EditorManager manager = this.masterEditor.MasterManager;
            if (manager.FormatBrush == null) return false;//不在“格式刷”状态

            PageEditor mainPageEditor = this.masterEditor;

            List<Widgets.Widget> destWidgets = new List<Widget>();
            destWidgets.Add(this);//格式化功能只需要自身一个即可。不更改兄弟部件的选定状态。

            //取出所有需要刷新位置的关系线。
            List<Widgets.Interfaces.ILinkableLine> linkedLines = mainPageEditor.GetLinkedLines(destWidgets);

            Point oldTopLeft = this.TopLeft;
            Point oldBottomRight = this.BottomRight;//备用，准备保持中心，未必使用。

            if (info == null)
            {
                info = new ModifingInfo();
                info.ModifingDescription = "格式化部件";
                manager.GetSelectedPageEditorStatus(info);
                manager.GetSelectedWidgetStatus_Old(info);
                manager.GetSelectedWidgetStatus_New(info);
            }

            bool shouldReg = false;
            if (mi == null)
            {
                shouldReg = true;
                mi = new ModifingItem<Action, ModifingInfo>(info);
            }

            //设置格式
            Action actOpacity = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.WidgetOpacityTag,
                this.WidgetOpacity.ToString(), manager.FormatBrush.DefaultWidgetStyle.WidgetOpacity.ToString());
            this.WidgetOpacity = manager.FormatBrush.DefaultWidgetStyle.WidgetOpacity;

            Action actBackColor = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.WidgetBackColor,
                BrushManager.GetName(this.WidgetBackColor),
                BrushManager.GetName(manager.FormatBrush.DefaultWidgetStyle.WidgetBackColor));
            this.WidgetBackColor = manager.FormatBrush.DefaultWidgetStyle.WidgetBackColor;

            Action actForeColor = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.WidgetForeColor,
                BrushManager.GetName(this.WidgetForeColor),
                BrushManager.GetName(manager.FormatBrush.DefaultWidgetStyle.WidgetForeColor));
            this.WidgetForeColor = manager.FormatBrush.DefaultWidgetStyle.WidgetForeColor;

            Action actLineColor = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.WidgetLineColorTag,
                BrushManager.GetName(this.WidgetLineColor),
                BrushManager.GetName(manager.FormatBrush.DefaultWidgetStyle.WidgetLineColor));
            this.WidgetLineColor = manager.FormatBrush.DefaultWidgetStyle.WidgetLineColor;

            Action actLineWidth = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.WidgetLineWidthTag,
                this.WidgetLineWidth.ToString(), manager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth.ToString());
            this.WidgetLineWidth = manager.FormatBrush.DefaultWidgetStyle.WidgetLineWidth;

            Action actWidgetPadding = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.WidgetPaddingTag,
                Globals.ThickConverter.ConvertToString(this.WidgetPadding),
                Globals.ThickConverter.ConvertToString(manager.FormatBrush.DefaultWidgetStyle.WidgetPadding));
            this.WidgetPadding = manager.FormatBrush.DefaultWidgetStyle.WidgetPadding;

            Action actIsShadowVisible = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.IsShadowVisibleTag,
                this.IsShadowVisible.ToString(), manager.FormatBrush.DefaultWidgetStyle.IsShadowVisible.ToString());
            this.IsShadowVisible = manager.FormatBrush.DefaultWidgetStyle.IsShadowVisible;

            Action actWidgetOutBorderType = new Action(mainPageEditor.Id, this.id, this.GetType().Name, XmlTags.OuterBorderTypeTag,
                this.OuterBorderType.ToString(), manager.FormatBrush.DefaultWidgetStyle.WidgetOutBorderType.ToString());
            this.OuterBorderType = manager.FormatBrush.DefaultWidgetStyle.WidgetOutBorderType;

            mi.AddAction(actOpacity); mi.AddAction(actBackColor); mi.AddAction(actForeColor); mi.AddAction(actLineColor);
            mi.AddAction(actWidgetPadding); mi.AddAction(actLineWidth); mi.AddAction(actIsShadowVisible); mi.AddAction(actWidgetOutBorderType);

            //如果是文本块且被挂接，自动保持过去的中心。
            if (linkedLines.Count > 0)
            {
                Point oldCenter = new Point(oldTopLeft.X + (oldBottomRight.X - oldTopLeft.X) / 2,
                    oldTopLeft.Y + (oldBottomRight.Y - oldTopLeft.Y) / 2);
                this.InvalidateArrange(); this.UpdateLayout();

                Point newTopLeft = this.TopLeft;
                Point newBottomRight = this.BottomRight;
                Point newLocation = new Point(oldCenter.X - (newBottomRight.X - newTopLeft.X) / 2,
                    oldCenter.Y - (newBottomRight.Y - newTopLeft.Y) / 2);

                Action actNewLocation = new Action(this.MasterEditor.Id, this.Id, this.GetType().Name, XmlTags.LocationTag,
                    this.Location.ToString(), newLocation.ToString());
                this.Location = newLocation;
                mi.AddAction(actNewLocation);
            }

            //刷新所有需要刷新位置的关系线。
            mainPageEditor.RefreshLinkedLines(mi, linkedLines);

            if (shouldReg)
            {
                manager.RegisterModifingItem(mi);

                if (manager.FormatBrush.OnlyFormatOnceTime)
                {
                    masterEditor.RaiseWidgetFormated(new List<Widgets.Widget>() { this });
                }
            }

            return true;
        }

        /// <summary>
        /// 取与自身挂接的连接线。
        /// </summary>
        /// <returns>可能返回null。</returns>
        public List<ILinkableLine> GetLinkedLines()
        {
            if (this.masterEditor == null) return null;

            List<Widget> widgets = new List<Widget>();
            widgets.Add(this);

            return this.masterEditor.GetLinkedLines(widgets);
        }

        /// <summary>
        /// 取内容部件的图像。返回RenderTargetBitmap对象。
        /// </summary>
        public RenderTargetBitmap GetRenderTargetBitmap()
        {
            double scale = ScaleValueConverter.GetNewScaleValue(Globals.MainWindow.SliderOfScale.Value);

            RenderTargetBitmap rtb = new RenderTargetBitmap(
                (int)(this.MainBorder.ActualWidth * scale),
                (int)(this.MainBorder.ActualHeight * scale),
                96, 96, PixelFormats.Pbgra32);

            rtb.Render(this.mainBorder);


            return rtb;
        }

        /// <summary>
        /// 准备拖出“关系（由两条直线、两个新文本框组成，或由一个文本框、一条直线组成）。
        /// </summary>
        void centerAdorner_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (masterEditor == null) return;
            if (e.ClickCount == 2)
            {
                //防止误拖动部件。
                if (masterEditor != null && masterEditor.MasterManager != null)
                {
                    masterEditor.MouseInfo.DraggingType = masterEditor.MasterManager.MouseDraggingType;
                }

                this.SelectOnlySelf();

                if (Globals.MainWindow.IsPresentatingByPath == false)
                {
                    this.Edit();
                }
                return;
            }

            e.Handled = true;
            if (Globals.MainWindow != null && Globals.MainWindow.EditorManager != null)
            {
                switch (Globals.MainWindow.EditorManager.MouseDraggingType)
                {
                    case PageDraggingType.InsertBezierLine:
                        {
                            masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.InsertBezierLineRelation;
                            break;
                        }
                    case PageDraggingType.InsertPolyLine:
                        {
                            masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.InsertPolyLineRelation;
                            break;
                        }
                    default:
                        {
                            masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.InsertStraitLineRelation;
                            break;
                        }
                }
            }
            else
            {
                masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.InsertStraitLineRelation;
            }

            //Point pt = e.GetPosition(this.masterEditor);//这个不好，会偏
            //pt = new Point(pt.X - this.masterEditor.BorderThickness.Left,
            //    pt.Y - this.masterEditor.BorderThickness.Top);

            Point pt = this.Center;//直接用中心点更好。
            masterEditor.MouseInfo.LeftButtonPreviewPoint = pt;
            masterEditor.MouseInfo.MainSelectedWidget = this;
        }

        void linkerAdorner_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            //设置链接到哪个页面。
            Dialogs.SetLinkedPageEditor slpe = new Dialogs.SetLinkedPageEditor(Globals.MainWindow, this);
            slpe.ShowDialog();
        }

        void linkerAdorner_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            //跳转到链接页面
            if (this.masterEditor == null)
            {
                masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
                return;
            }

            if (this.masterEditor.MasterManager == null)
            {
                masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
                return;
            }

            Point curPoint = e.GetPosition(this.masterEditor.BaseCanvas);

            masterEditor.MouseInfo.LeftButtonPoint = curPoint;
            if (masterEditor.MouseInfo.DraggingType != PageDraggingType.JumpToLinkedPageEditor)
            {
                masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
                return;
            }

            if (Math.Abs(curPoint.X - masterEditor.MouseInfo.LeftButtonPreviewPoint.X) > 4 ||
                Math.Abs(curPoint.Y - masterEditor.MouseInfo.LeftButtonPreviewPoint.Y) > 4)
            {
                masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
                return;//移动距离大，不算点击跳转区。
            }

            PageEditor destPageEditor = this.masterEditor.MasterManager.GetPageEditor(this.linkedPageEditorId);
            if (destPageEditor == null)
            {
                MessageBox.Show("　　没有指定链接目标页，或者链接目标页已经被删除。", Globals.AppName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
                return;
            }

            if (destPageEditor.Id == this.masterEditor.Id)
            {
                MessageBox.Show("　　链接目标页面就是此部件所在的页面。无需跳转。", Globals.AppName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
                return;
            }

            this.SelectOnlySelf();
            this.IsSelected = false;

            foreach (UIElement ue in this.masterEditor.MasterManager.Children)
            {
                PageEditor pe = ue as PageEditor;
                if (pe == null) continue;

                pe.IsSelected = false;
            }

            destPageEditor.IsMainSelected = true;
            this.masterEditor.MasterManager.TryToDisplayPageEditor(destPageEditor);
            e.Handled = true;//避免移动页面时误操作。

            masterEditor.MouseInfo.DraggingType = PageDraggingType.None;
        }

        void linkerAdorner_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //准备跳转。
            if (masterEditor != null)
            {
                masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.JumpToLinkedPageEditor;
                Point pt = e.GetPosition(this.masterEditor);
                pt = new Point(pt.X - this.masterEditor.BorderThickness.Left, pt.Y - this.masterEditor.BorderThickness.Top);
                masterEditor.MouseInfo.LeftButtonPreviewPoint = pt;
            }
            e.Handled = true;//防止误更改masterEditor.MouseInfo.DraggingType

            //masterEditor.MouseInfo.DraggingType = PageDraggingType.None;//一加就跳转不了了。
        }

        void maskAdorner_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            mainBorder_PreviewMouseLeftButtonDown(sender, e);
        }

        /// <summary>
        /// 选定部件，准备拖动。
        /// </summary>
        void mainBorder_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            ModifingItem<Action, ModifingInfo> mi = null;
            ModifingInfo info = null;
            if (this.FormatSelf(ref mi, ref info)) return;//格式化部件，不再更改选定状态。

            e.Handled = true;

            //双击则编辑。
            if (e.ClickCount == 2)
            {
                //防止误拖动部件。
                if (masterEditor != null && masterEditor.MasterManager != null)
                {
                    masterEditor.MouseInfo.DraggingType = masterEditor.MasterManager.MouseDraggingType;
                }

                this.SelectOnlySelf();

                if (Globals.MainWindow.IsPresentatingByPath == false)
                {
                    this.Edit();
                }
                return;
            }
            else
            {
                bool isShift = false;
                KeyStates ksRightShift = Keyboard.GetKeyStates(Key.RightShift);
                KeyStates ksLeftShift = Keyboard.GetKeyStates(Key.LeftShift);

                if ((ksRightShift & KeyStates.Down) > 0 || (ksLeftShift & KeyStates.Down) > 0) isShift = true;

                bool isCtrl = false;
                KeyStates ksRightCtrl = Keyboard.GetKeyStates(Key.RightCtrl);
                KeyStates ksLeftCtrl = Keyboard.GetKeyStates(Key.LeftCtrl);

                if ((ksRightCtrl & KeyStates.Down) > 0 || (ksLeftCtrl & KeyStates.Down) > 0) isCtrl = true;

                if (isShift && isCtrl == false)
                {
                    //基本规则：
                    //    ①如果未选定，选定，并作为活动部件。
                    //    ②如果已选定，看是否是活动部件，如果已经是活动部件，整个取消选定状态；
                    //                                      如果不是活动部件，设为活动部件。
                    if (this.IsSelected == false)
                    {
                        this.IsMainSelected = true;
                    }
                    else
                    {
                        if (this.IsMainSelected == false)
                        {
                            this.IsMainSelected = true;
                        }
                        else
                        {
                            this.IsSelected = false;
                        }
                    }
                }
                else
                {
                    if (IsSelected == false)//如果没有选定，就先选定。如果已经选定，说明是要拖动。
                    {
                        SelectOnlySelf();
                    }
                    //如果是选定的部件，那么可能是在拖动。
                }
            }

            //准备拖动。
            if (masterEditor != null && Globals.MainWindow.IsPresentatingByPath == false)
            {
                masterEditor.MouseInfo.DraggingType = Enums.PageDraggingType.MoveWidgets;
                Point pt = e.GetPosition(this.masterEditor);
                pt = new Point(pt.X - this.masterEditor.BorderThickness.Left, pt.Y - this.masterEditor.BorderThickness.Top);
                masterEditor.MouseInfo.LeftButtonPreviewPoint = pt;
            }
        }

        /// <summary>
        /// 禁止MouseLeftButtonUp事件向下传递。
        /// </summary>
        void mainBorder_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            //e.Handled = true;//有这句就无法更新Ribbon上按钮的状态了。这个事件不能截断。

            //2012年2月21日，将PageEditor的选定框改回使用装饰器来实现，结果意外发现：
            //保留下面这些代码会导致按Shift点击ContentWidget时可以实现多选ContentWidget，
            //——但一旦松开鼠标左键，立即会“只选定ContentWidget本身”！！！！
            //if (masterEditor != null)
            //{
            //    Point curPoint = e.GetPosition(masterEditor);
            //    if (Math.Abs(masterEditor.MouseInfo.LeftButtonPreviewPoint.X - curPoint.X) <= 4 &&
            //        Math.Abs(masterEditor.MouseInfo.LeftButtonPreviewPoint.Y - curPoint.Y) <= 4)
            //    {
            //        //this.SelectOnlySelf();
            //    }
            //}
        }

        /// <summary>
        /// 只为将来弹出右键菜单准备。2012年1月3日
        /// </summary>
        void mainBorder_PreviewMouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            e.Handled = true;

            if (this.IsSelected == false)
            {
                //如果未选定，就作为活动，
                this.SelectOnlySelf();
            }
            else
            {
                //若已选定，不更改选定范围，只更改“活动部件”为此部件
                if (this.IsMainSelected == false) this.IsMainSelected = true;
            }

            if (this.ContextMenu != null)
            {
                this.ContextMenu.IsOpen = true;
            }
        }

        /// <summary>
        /// 改变中心点横坐标。
        /// </summary>
        public override void MoveHorizontalCenterTo(ModifingItem<Action, ModifingInfo> mi, double center)
        {
            if (mi == null || double.IsNaN(center) || masterEditor == null) return;

            double offset = 0;
            double curCenter = TopLeft.X + (BottomRight.X - TopLeft.X) / 2;
            offset = curCenter - center;

            Point newLocation = new Point(location.X - offset, location.Y);
            Action actLocation = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.LocationTag,
                location.ToString(), newLocation.ToString());
            this.Location = newLocation;

            mi.AddAction(actLocation);
        }

        /// <summary>
        /// 改变中心点纵坐标。
        /// </summary>
        public override void MoveVerticalCenterTo(ModifingItem<Action, ModifingInfo> mi, double center)
        {
            if (mi == null || double.IsNaN(center) || masterEditor == null) return;

            double offset = 0;
            double curCenter = TopLeft.Y + (BottomRight.Y - TopLeft.Y) / 2;
            offset = curCenter - center;

            Point newLocation = new Point(location.X, location.Y - offset);
            Action actLocation = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.LocationTag,
                location.ToString(), newLocation.ToString());
            this.Location = newLocation;

            mi.AddAction(actLocation);
        }

        /// <summary>
        /// 与MoveDown不同，这里是指定向下移动到哪个位置（下边缘到哪个位置）。
        /// </summary>
        public override void MoveBottomSiderTo(ModifingItem<Action, ModifingInfo> mi, double bottom)
        {
            double offset = BottomRight.Y - bottom;

            Point newLocation = new Point(location.X, location.Y - offset);

            Action act = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.LocationTag,
                location.ToString(), newLocation.ToString());

            Location = newLocation;

            mi.AddAction(act);
        }

        /// <summary>
        /// 与MoveLeft不同，这里是指定向左移动到哪个位置（左边缘到哪个位置）。
        /// </summary>
        public override void MoveLeftSiderTo(ModifingItem<Action, ModifingInfo> mi, double left)
        {
            double offset = location.X - left;

            Point newLocation = new Point(location.X - offset, location.Y);

            Action act = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.LocationTag,
                location.ToString(), newLocation.ToString());

            Location = newLocation;

            mi.AddAction(act);
        }

        /// <summary>
        /// 与MoveRight不同，这里是指定向右移动到哪个位置（右边缘到哪个位置）。
        /// </summary>
        public override void MoveRightSiderTo(ModifingItem<Action, ModifingInfo> mi, double right)
        {
            double offset = BottomRight.X - right;

            Point newLocation = new Point(location.X - offset, location.Y);

            Action act = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.LocationTag,
                location.ToString(), newLocation.ToString());

            Location = newLocation;

            mi.AddAction(act);
        }

        /// <summary>
        /// 与MoveUp不同，这里是指定向上移动到哪个位置（上边缘到哪个位置）。
        /// </summary>
        public override void MoveTopSiderTo(ModifingItem<Action, ModifingInfo> mi, double top)
        {
            double offset = location.Y - top;

            Point newLocation = new Point(location.X, location.Y - offset);

            Action act = new Action(masterEditor.Id, id, this.GetType().Name, XmlTags.LocationTag,
                location.ToString(), newLocation.ToString());

            Location = newLocation;

            mi.AddAction(act);
        }

        /// <summary>
        /// 拖动时动态改变各部件位置。
        /// </summary>
        /// <param name="mainSelectedLocationWidget">应传入MainSelectedWidget。</param>
        /// <param name="mouseCurrentPoint">当前鼠标指针的位置。</param>
        public static void MoveWhenDraggingWidget(ContentWidget mainSelectedLocationWidget, Point mouseCurrentPoint)
        {
            if (mainSelectedLocationWidget == null || mainSelectedLocationWidget.masterEditor == null ||
                mainSelectedLocationWidget.masterEditor.MasterManager == null) return;

            if (mainSelectedLocationWidget.masterEditor.MouseInfo.DraggingType ==
                Enums.PageDraggingType.MoveWidgets)
            {
                List<Widget> selectedWidgetsList = mainSelectedLocationWidget.masterEditor.GetSelectedWidgetsList();

                foreach (Widget w in selectedWidgetsList)
                {
                    ContentWidget cw = w as ContentWidget;
                    if (cw != null)
                    {
                        double hOffset = mainSelectedLocationWidget.masterEditor.MouseInfo.
                            LeftButtonPreviewPoint.X - cw.location.X;
                        double vOffset = mainSelectedLocationWidget.masterEditor.MouseInfo.
                            LeftButtonPreviewPoint.Y - cw.location.Y;

                        Canvas.SetLeft(cw, mouseCurrentPoint.X - hOffset);
                        Canvas.SetLeft(cw, mouseCurrentPoint.Y - vOffset);
                    }
                }
            }
        }

        /// <summary>
        /// 刷新“被选定状态”——其实就是使“选定框”装饰器重绘。
        /// </summary>
        public override void RefreshIsSelected()
        {
            base.RefreshIsSelected();

            this.selectedAdorner.InvalidateVisual();
            //this.centerAdorner.InvalidateVisual();//会导致字看不清。
        }

        public override void RefreshIsShadowVisible()
        {
            if (isShadowVisible)
            {
                //this.mainTextPanel.Effect =//保持文本清晰
                this.mainBorder.Effect = Widget.ShadowEffect;
            }
            else
            {
                //this.mainTextPanel.Effect =
                this.mainBorder.Effect = null;
            }
        }

        /// <summary>
        /// Location设置好后，刷新部件位置。
        /// </summary>
        public override void RefreshLocation()
        {
            Canvas.SetLeft(this, location.X);
            Canvas.SetTop(this, location.Y);

            this.RefreshCommentText();
            this.RefreshHyperLinkText();

            this.RefreshTextPanelLocatin();
            this.RefreshTextRotateAngle();
            this.RefreshOuterBorderType();
        }

        /// <summary>
        /// 刷新顶注释与底注释文本。——这与所有部件均支持的备注文本不同。
        /// </summary>
        public void RefreshCustomCommentText()
        {
            if (this.commentTopText != null && this.commentTopText.Length > 0)
            {
                if (this.commentTopAdorner == null)
                {
                    this.commentTopAdorner = new WidgetCommentAdorner(this.mainBorder,
                        this, WidgetCommentAdorner.Location.Top);
                    this.AdornerLayer.Add(this.commentTopAdorner);
                }

            }

            if (this.commentTopAdorner != null)
            {
                this.commentTopAdorner.InvalidateVisual();
            }

            if (this.commentBottomText != null && this.commentBottomText.Length > 0)
            {
                if (this.commentBottomAdorner == null)
                {
                    this.commentBottomAdorner = new WidgetCommentAdorner(this.mainBorder,
                        this, WidgetCommentAdorner.Location.Bottom);
                    this.AdornerLayer.Add(this.commentBottomAdorner);
                }

            }

            if (this.commentBottomAdorner != null)
            {
                this.commentBottomAdorner.InvalidateVisual();
            }
        }

        /// <summary>
        /// 刷新遮罩状态。
        /// </summary>
        public void RefreshMask()
        {
            this.maskAdorner.InvalidateVisual();
        }

        /// <summary>
        /// 刷新外框类型。
        /// </summary>
        public void RefreshOuterBorderType()
        {
            //switch (this.outerBorderType)
            //{
            //    case Enums.OuterBorderType.Rect:
            //        {
            //            this.mainBorder.BorderBrush = this.widgetLineColor;
            //            this.outerBorderAdorner.Visibility = Visibility.Collapsed;
            //            return;//直接返回
            //        }
            //    default:
            //        {
            //            this.mainBorder.BorderBrush = Brushes.Transparent;//其它全不显示。
            //            this.outerBorderAdorner.Visibility = Visibility.Visible;
            //            break;
            //        }
            //}
            // 改用外框来实现，因为 mainBorder 不能支持旋转
            this.mainBorder.BorderBrush = Brushes.Transparent;
            this.outerBorderAdorner.Visibility = Visibility.Visible;

            if (this.outerBorderAdorner != null)
            {
                this.outerBorderAdorner.InvalidateVisual();
            }
        }

        /// <summary>
        /// 刷新文本区旋转角度。
        /// </summary>
        public virtual void RefreshTextRotateAngle()
        {
            
        }

        /// <summary>
        /// WidgetBackground属性值改变时会调用此方法刷新部件的背景色。
        /// ——亦可根据需要调用。
        /// ——默认直接改变mainBorder的背景色。派生类可自行定义行为。
        /// </summary>
        public override void RefreshWidgetBackColor()
        {
            if (this.mainBorder != null)
                this.mainBorder.Background = widgetBackColor;
            this.RefreshMask();
        }

        /// <summary>
        /// WidgetBorderBrush属性值改变时会调用此方法刷新部件边框色。
        /// ——亦可根据需要调用。
        /// ——默认直接更改mainBorder的边框色。派生类可自行定义行为。
        /// </summary>
        public override void RefreshWidgetLineColor()
        {
            //switch (this.outerBorderType)
            //{
            //    case Enums.OuterBorderType.Rect:
            //        {
            //            if (this.mainBorder != null)
            //                this.mainBorder.BorderBrush = Brushes.Transparent;  // 改用 OuterBorder 实现，Border 无法支持旋转。
            //            break;
            //        }
            //    default:
            //        {
            //            if (this.mainBorder != null)
            //                this.mainBorder.BorderBrush = Brushes.Transparent;
            //            break;
            //        }
            //}
            mainBorder.BorderBrush = Brushes.Transparent; // 总是透明好了。改用 OuterBorder 实现，Border 无法支持旋转。

            this.RefreshOuterBorderType();
        }

        //2012年6月26日，取消WidgetBorderWidth属性，改用WidgetLineWidth属性。
        //public virtual void RefreshWidgetBorderWidth()
        //{
        //    if (this.mainBorder != null)
        //        this.mainBorder.BorderThickness = new Thickness(this.widgetBorderWidth);
        //}

        public override void RefreshWidgetLineWidth()
        {
            if (this.mainBorder != null)
                this.mainBorder.BorderThickness = new Thickness(this.widgetLineWidth);
        }

        public override void RefreshWidgetForeColor()
        {
            base.RefreshWidgetForeColor();

            this.RefreshMask();
        }

        public virtual void RefreshWidgetPadding()
        {
            if (this.mainBorder != null)
                this.mainBorder.Padding = this.widgetPadding;
        }

        #endregion
    }
}
